iT邦幫忙

2022 iThome 鐵人賽

DAY 2
0
Modern Web

咩色用得好,歸剛沒煩惱 - 從 ECMAScript 偷窺 JavaScript Array method系列 第 2

Day 2 咩色用得好 - 關於 Array method,你可以再知道多一些些

  • 分享至 

  • xImage
  •  

Prelude

我是阿傑,前一篇講到 Array method 其實藏了不少 JavaScript 的知識點跟特性,雖然不清楚這些也不大影響使用 Array method 的流暢性,但瞭解多一點可以使用得更加得心應手,這邊我們會簡單聊聊你可以知道的一些關於 JavaScript 的事情。

老實說,這樣的歸類其實不是很精準,因為有些概念並非是 JavaScript 這個語言獨有的,這裡只是為了跟 ECMAScript 的用詞及概念做個簡單的區分!

以下會聊聊 4 個我覺得重要的名詞:


Prototype

簡單來講,prototype 就是一個物件,它最大的功用就是分享自身的屬性給其他物件,JavaScript 的繼承 (inheritance) 就是靠它做到的。

你需要知道的是 - 所有的 Array instance (實例),不管是用 Array()Array.from()Array literal 創造出來的陣列,它們的 [[prototype]] 都會指向同一個 prototype 物件,也就是 Array.prototype 所指向的 prototype 物件。

而我們所使用的 Array method 大部分都被放在 Array.prototype 指向的這個 prototype 物件裡,因此當我們在 Array instance 取用這些 method 時,它便會順著 prototype chain (原型鏈) 往上找到 [[Prototype]] 所指向的物件,並取用同名的 method。

換句話說, Array.prototype[[Prototype]] 所指向的這個 prototype 物件 分享了它的 method 給底下的所有 array instance,因此所有的 array instance 都可以使用這些 method,即便它們本身沒有定義這些 method。

這就是一般的日常使用 (圖 2.1):

2.1

Note: [[Prototype]] 是 ECMAScript 規定的一個 internal slot,它並沒有要求實作將其曝露出來,所以 JavaScript 無法看得到它,但可以藉由瀏覽器來偷窺一下(圖 2.2)。

2.2


Callback Function

為什麼 callback 要拿出來講?因為有將近一半的 Array method 都會使用到 callback,知道 callback 會如何運作絕對是 Z 大於 B。

如果你去 Google “callback function”,應該會得到一個非常棒的答案 - “一個函式被當作參數傳入另一個函式...”,我知道你在想什麼...

究竟是錯付了

那我們再接著問一個問題 - 為什麼它可以被當成參數傳遞?因為 function 在 JavaScript 被當成是頭等物件,可以參考 MDN 的說明!而當它可以像參數一樣傳遞給另一個 function (higher-order function )時,這個接收它的 higher-order function 就可以隨意地使用它。

可以把 callback 想像成你寫了一段程式碼後交給了某人 (higher-order function) 使用,他便因此擁有了你程式碼的控制權,這意味著他可以在任何時機點呼叫這個 callback,而且我們還很貼心地照著他給的藍圖寫了這個 callback,包括該定義什麼參數、該回傳什麼,如果這個某人恰巧是某個不懷好意的第三方程式庫 (third-party library),那這個控制權轉移 (inversion of control) 將會是危險的,但這不在我們本次討論的範疇,你該瞭解的是 - 你傳進 Array method 的 callback 將會被如何使用。

我們直接拿 ECMAScript 裡的 Array.prototype.every來看 (圖 2.3):

2.3

  • 從上面可以看到,callback 被這個 higher-order function (every() method) 放在了一段迴圈裡面 (Repeat),而這個迴圈重複的最大次數會是陣列的長度,也就是說這個 callback 被呼叫的次數最多會等於陣列的長度 (如果陣列長度為 5,那它可能至多會被呼叫 5次)。

  • 這個 every() method 每次呼叫 callback 時,都會帶入 kValueF(k)O 這三個引數,對應的是我們所熟知的 elementindexarray ,也就是我們在定義 callback 時的三個參數 (parameter)。

  • 而它又對 callback 回傳的值進行布林的轉換,變相規定了這個 callback 必須回傳布林值。

從上面可以看到我們的 callback 在哪裡被呼叫?被呼叫了幾次?它被帶進了什麼引數 (argument)?所以我們需要定義哪些相對應的參數 (parameter)?並且回傳什麼型別的值?

當清楚知道自己的 callback 將會被如何使用,我想你就應該知道如何撰寫它了!


This

你應該多少聽過 this 這個東西是整個 JavaScript 最容易讓人混淆的東西之一, 因為它牽涉到很多不易直接觀察到的東西,包括運行中的執行環境 (running execution context)、及其語彙環境 (LexicalEnvironment)、甚至還有 new 運算子會左右它的綁定 (binding) 或箭頭函式 (arrow function) 產生的意外結果。

但先別緊張,你暫時只需要知道 - 當使用一個陣列來呼叫一個 method,這個 method 內部 (function body) 的 this 指的就是這個取用它的陣列,換句話說,我們可以將這個 this 關鍵字 (keyword) 直接替換成當前的陣列。

舉個例子,我們拿 Array.prototype.some 來看:

const names = ['Pedro', 'Anita', 'Damien'];

const isAnitaThere = names.some(name => name === 'Anita');
// 在 some() 的 function body 內出現的 this 指向的會跟 names 是同一個陣列


console.log(isAnitaThere)  
// true

雖然這邊無法得知 some() 的 function body 寫了什麼,在什麼地方使用了 this,但我們可以從 ECMAScript 的 Array.prototype.some() 來推敲一二,例如(圖 2.4):

2.4

這邊的 this 被嘗試轉成物件後指派給 O!簡單的說,當你使用一個陣列呼叫一個 Array method, this 代表的就是這個陣列本身。


Immutable & Mutable

如果去 Google 這個詞彙,可能會得到一個結論 - "在 JavaScript 中,基本型別 (primitive) 是 immutable,而物件型別 (object, array) 是 mutable",雖然它的原理跟脈絡不在我們這邊討論的範圍,但在 Array method 的操作中,這件事就顯得格外重要。

先用一句話概括 - 這個 Array method 會不會改動到原陣列!

例如以下幾個 method 會改動到原陣列:

  • Array.prototype.pop()
  • Array.prototype.sort()
  • Array.prototype.splice()

而下面這幾個則是回傳新陣列,不改動到原陣列:

  • Array.prototype.slice()
  • Array.prototype.map()
  • Array.prototype.filter()

為什麼需要知道這些,因為我們很容易在不知情的狀況下變動到不該變動的東西,這樣會產生很多非預期的情況,我想這應該也不是你樂見的。

Note:
如果你不確定這個 method 是否會改動的原陣列,可以參考 MDN,因為 ECMAScript 並沒有直接講明這件事。


Conclusion

上述聊的這些都只是簡略的帶過,目的只是希望可以幫助你理解 Array method,它們值得你花更多時間去研究、探討,我們將會在 Day 4、Day 5 聊聊你該知道的 ECMAScript 術語!

希望大家可以開心地使用各種咩色,體驗它帶給你的便利,祝大家歸剛沒煩惱。


參考資源


上一篇
Day 1 咩色用得好 - 給我一個用 Array Method 的理由
下一篇
Day 3 咩色用得好 - ECMAScript 該從哪邊下手啊?
系列文
咩色用得好,歸剛沒煩惱 - 從 ECMAScript 偷窺 JavaScript Array method30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言